package com.corpgovernment.organization.service.impl;

import cn.hutool.core.util.StrUtil;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.dataloader.db.*;
import com.corpgovernment.organization.entity.db.MbOrgEmployeeInfo;
import com.corpgovernment.organization.model.*;
import com.corpgovernment.organization.service.CtripOpenCardService;
import com.corpgovernment.organization.service.OpenCardService;
import com.corpgovernment.supplier.constant.CommonConstant;
import com.corpgovernment.supplier.dto.OpenCardEmployeeDTO;
import com.corpgovernment.supplier.vo.OpenCardDetailListInfoVo;
import com.corpgovernment.supplier.vo.OpenCardListInfoVo;
import com.corpgovernment.supplier.vo.suppliercompany.SyncOpenCardResponseVo;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.Conditional;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zl.cui
 * @date 2023/10/12
 */
@Component
@Slf4j
public class OpenCardServiceImpl implements OpenCardService {
    @Autowired
    private EmployeeOpenCardRecordLoader employeeOpenCardRecordLoader;
    @Autowired
    private MbUserOrgRelationLoader mbUserOrgRelationLoader;
    @Autowired
    private MbOrgInfoLoader mbOrgInfoLoader;
    @Autowired
    private MbSupplierCompanyLoader mbSupplierCompanyLoader;
    @Autowired
    private CtripOpenCardService ctripOpenCardService;
    @Autowired
    private MbOrgEmployeeLoader mbOrgEmployeeLoader;
    @Autowired
    @Qualifier(value = "defaultThreadPoolExecutor")
    private ThreadPoolExecutor defaultThreadPoolExecutor;

    /**
     * 限制最大递归次数
     */
    private static final int MAX_RECURSION_TIMES = 10;
    @Override
    public SyncOpenCardResponseVo applyOpenCard(String orgId, String accountName) {
        List<OpenCardEmployeeModel> openCardEmployeeModelList = Collections.emptyList();
        List<OpenCardEmployeeModel> failedList = Collections.emptyList();
        try {
             openCardEmployeeModelList = getNeedOpenCardEmployee(orgId);
            List<OpenCardEmployeeModel> finalOpenCardEmployeeModelList = openCardEmployeeModelList;

            log.info("用户集合：{}", JsonUtils.toJsonString(finalOpenCardEmployeeModelList));
            List<SupplierCompanyModel> companyConfigList = ctripOpenCardService.getParentConfig(orgId);
            // 过滤开启一人一卡的配置
            if(CollectionUtils.isNotEmpty(companyConfigList)){
                companyConfigList = companyConfigList.stream().filter( x->x.getOpenCardType().equals("X")).collect(Collectors.toList());
            }
            if (CollectionUtils.isEmpty(companyConfigList) || StringUtils.isBlank(companyConfigList.get(0).getSubAccountCode())){
                log.error("orgId:{}配置为空", orgId);
                throw new CorpBusinessException(OrganizationResponseCodeEnum.COMPANY_ACCOUNT_CONFIG_EMPTY);
            }
            SupplierCompanyModel companyConfig = companyConfigList.get(0);
            Long key = ctripOpenCardService.generateKey(finalOpenCardEmployeeModelList.size(), orgId,accountName,companyConfig);
            finalOpenCardEmployeeModelList.forEach(t->t.setBatchNo(key));
            CompletableFuture.supplyAsync(()-> ctripOpenCardService.openCard(orgId, finalOpenCardEmployeeModelList, companyConfig), defaultThreadPoolExecutor);
            return buildResponse(failedList, openCardEmployeeModelList.size(), 0);
        }catch (Exception e){
            log.error("员工开卡异常：", e);
        }
        return buildResponse(Collections.emptyList(), openCardEmployeeModelList.size() - failedList.size(), failedList.size());
    }

    @Override
    public OpenCardListInfoVo getOpenCardRecord(String orgId, int pageNum, int pageSize, String subAccountCode, String subAccountId){
        return ctripOpenCardService.getOpenCardResult(orgId, pageNum, pageSize,subAccountCode,subAccountId);
    }

    @Override
    public OpenCardDetailListInfoVo getOpenCardRecordDetail(String orgId, String batchNo, int pageNum, int pageSize, Integer failedType) {
        return ctripOpenCardService.getOpenCardDetailResult(orgId,batchNo, pageNum, pageSize,failedType);
    }


    private SyncOpenCardResponseVo buildResponse(List<OpenCardEmployeeModel> failedList, Integer successNum, Integer failedNum){
        SyncOpenCardResponseVo response = new SyncOpenCardResponseVo();
        response.setSuccessNum(successNum);
        response.setFailedNum(failedNum);
        List<OpenCardEmployeeDTO> failedDtoList = Conditional.ofEmptyAble(failedList).orElse(Collections.emptyList()).stream().map(failedItem ->{
            OpenCardEmployeeDTO openCardEmployeeDTO = new OpenCardEmployeeDTO();
            openCardEmployeeDTO.setName(failedItem.getName());
            openCardEmployeeDTO.setOpenCardFailedContent(failedItem.getOpenCardFailedContent());
            openCardEmployeeDTO.setGender(failedItem.getGender());
            openCardEmployeeDTO.setEmail(failedItem.getEmail());
            openCardEmployeeDTO.setBirthday(failedItem.getBirthday());
            openCardEmployeeDTO.setUid(failedItem.getUid());
            openCardEmployeeDTO.setNationality(failedItem.getNationality());
            openCardEmployeeDTO.setAreaCode(failedItem.getAreaCode());
            openCardEmployeeDTO.setMobilePhone(failedItem.getMobilePhone());
            return openCardEmployeeDTO;
        }).collect(Collectors.toList());
        response.setFailedList(failedDtoList);
        return response;
    }


    /**
     * 获取需要开卡&开卡失败
     *
     * @return
     */
    private List<OpenCardEmployeeModel> getNeedOpenCardEmployee(String orgId){
        // 获取orgId下所有组织id
        List<String> childrenOrgIdList = getAllChildrenOrgInfo(new ArrayList<>(Collections.singletonList(orgId)), new ArrayList<>(Collections.singletonList(orgId)), 0);
        // 根据组织id获取所有的关联的uid
        List<MbUserOrgRelationModel> relationModelList = mbUserOrgRelationLoader.getRelationByOrgIdList(childrenOrgIdList);
        log.info("根据组织id获取所有的关联的relationModelList:{}", JsonUtils.toJsonString(relationModelList));
        List<String> relationUidList = relationModelList.stream().map(MbUserOrgRelationModel::getUid).collect(Collectors.toList());
        List<MbOrgEmployeeInfo> needOpenCardList = mbOrgEmployeeLoader.selectActiveEmployeeByUids(
                relationUidList);
        log.info("needOpenCardList:{}", JsonUtils.toJsonString(needOpenCardList));
        if (CollectionUtils.isEmpty(needOpenCardList)){
            return Collections.emptyList();
        }
        // 获取uid对应的开卡记录(已经开卡的)
        List<MbOrgEmployeeOpenCardRecordModel> hasOpenCardList = employeeOpenCardRecordLoader.getOpenCardRecordList(relationUidList);
        log.info("获取uid对应的开卡记录(已经开卡的):{}", JsonUtils.toJsonString(hasOpenCardList));
        Map<String, MbOrgEmployeeOpenCardRecordModel> hasOpenCardMap =
                hasOpenCardList.stream().collect(Collectors.toMap(MbOrgEmployeeOpenCardRecordModel::getPlatUid, Function.identity(), (t1, t2) -> t1));
        // 获取子账户配置
        List<SupplierCompanyModel> supplierCompanyModelList = mbSupplierCompanyLoader.getSupplierCompanyConfig(orgId, CommonConstant.CTRIP_CODE);
        log.info("获取子账户配置:{}", JsonUtils.toJsonString(supplierCompanyModelList));

        // 当前租户法人公司是否同步
        Boolean corporateEntityFlag = false;
        if (CollectionUtils.isNotEmpty(supplierCompanyModelList)) {
            corporateEntityFlag = ctripOpenCardService.getCorporateEntitySyncFlag();

            // 和当前配置不一致的才需要更新卡的信息
            needOpenCardList = needOpenCardList.stream()
                    .filter(t -> {
                        String subAccountCode = Conditional.ofNullable(hasOpenCardMap.get(t.getUid()))
                                .map(MbOrgEmployeeOpenCardRecordModel::getSubAccountName).orElse(null);
                        String corporateEntity = Conditional.ofNullable(hasOpenCardMap.get(t.getUid()))
                                .map(MbOrgEmployeeOpenCardRecordModel::getCorporateEntity).orElse(null);
                        boolean hasConfigSendEmail = Conditional.ofNullable(hasOpenCardMap.get(t.getUid()))
                                .map(MbOrgEmployeeOpenCardRecordModel::getSetDefaultSendConfig).orElse(false);
                        log.info("开卡比较字段：subAccountCode{}.corporateEntity{}. empAccountCode{},empCorporateEntity{}",
                                subAccountCode, corporateEntity, supplierCompanyModelList.get(0).getSubAccountCode(),
                                t.getCorporateEntity());
                        return !(supplierCompanyModelList.get(0).getSubAccountCode().equals(subAccountCode))
                           || !StrUtil.equals(t.getCorporateEntity(), corporateEntity) || !hasConfigSendEmail;
                    })
                    .collect(Collectors.toList());
        }
        log.info("最终开卡列表:{}", JsonUtils.toJsonString(needOpenCardList));
        if (CollectionUtils.isEmpty(needOpenCardList)){
            return Collections.emptyList();
        }

        Boolean finalCorporateEntityFlag = corporateEntityFlag;
        return needOpenCardList.stream().map(mbOrgEmployeeInfo -> {
            OpenCardEmployeeModel model = new OpenCardEmployeeModel();
            model.setUid(mbOrgEmployeeInfo.getUid());
            model.setBirthday(mbOrgEmployeeInfo.getBirthday());
            model.setGender(mbOrgEmployeeInfo.getGender());
            model.setEmail(mbOrgEmployeeInfo.getEmail());
            model.setNationality(mbOrgEmployeeInfo.getNationality());
            model.setName(mbOrgEmployeeInfo.getName());
            model.setAreaCode(mbOrgEmployeeInfo.getAreaCode());
            model.setMobilePhone(mbOrgEmployeeInfo.getMobilePhone());
            if(finalCorporateEntityFlag) {
                model.setCorporateEntity(mbOrgEmployeeInfo.getCorporateEntity());
            }
            return model;
        }).collect(Collectors.toList());

    }

    /**
     * 递归获取所有的子组织id
     * @return
     */
    private List<String> getAllChildrenOrgInfo(List<String> saveList, List<String> parentList, int recursionTimes){
        if (recursionTimes > MAX_RECURSION_TIMES){
            return Collections.emptyList();
        }
        List<MbOrgInfoModel> mbOrgInfoList = mbOrgInfoLoader.selectOrgByParentIdList(parentList);
        // 没有子组织了
        if (CollectionUtils.isEmpty(mbOrgInfoList)){
            return saveList;
        }
        List<String> orgIdList = mbOrgInfoList.stream()
                .map(MbOrgInfoModel::getOrgId)
                .collect(Collectors.toList());
        saveList.addAll(orgIdList);
        // 递归查询子组织id
        getAllChildrenOrgInfo(saveList, orgIdList,recursionTimes + 1);

        return saveList;
    }
}
